module ActiveBackground
  class Chef < ActiveBackground::Handler

    # initialize implementation by including the default worker directories
    def initialize
      super
      Dir.foreach(File.dirname(__FILE__) + "/../../workers/") do |file|
        if file != "." && file != ".."
          require File.dirname(__FILE__) + "/../../workers/" + file
        end
      end
    end
    
    # retrieves the worker from one of the registered directories
    # and passes it on to the server.
    # 
    # Arguments:
    #     <tt>worker</tt>: Name of worker can be passed, unless
    #     options[:class], name is converted to class name.
    #     <tt>options</tt>: Hash of options allow you to specify worker creation parameters.
    #     <tt>argv</tt>: Hash of argv are passed on to the worker (without modification).
    #     
    # Options:
    # 
    #     <tt>:class</tt>: Name of worker passed as a symbol
    #     <tt>:key</tt>: Uniq key that is assigned to the worker (uniq key is
    #     genenerated if no :key is passed)
    def new_worker(worker, options={}, *argv)

      klass = options[:class] || worker
      # convert class name (symbol) to constant and initialize
      begin
        worker = get_worker_class(klass).new(worker, options, argv)
      rescue Exception => e # couldn't find worker
        debug = e.to_s + "\n" + e.backtrace.join("\n") if $ACTIVE_BACKGROUND_DEBUG
        ACTIVE_BACKGROUND_LOGGER.warn(
          " * ActiveBackground::Chef(Worker does not exist)\n" +
          debug || ""
        )
        raise "Worker does not exist, please make sure you have registered " +
              "the directory that contains the worker"
      end

      # try to pass a job to the server thru MiddleMan
      begin
        # pass the initialized worker to the server thru the MiddleMan class
        @middle_man.add_job(worker.key, worker)
        # return the worker (job) key. This allows to fetch the worker when needed.
        return worker.key
      rescue Exception => e # something went wrong while creating the worker
        debug = e.to_s + "\n" + e.backtrace.join("\n") if $ACTIVE_BACKGROUND_DEBUG
        ACTIVE_BACKGROUND_LOGGER.warn(
          " * ActiveBackground::Chef(Cannot create worker)\n" +
          debug || ""
        )
        raise "Something went wrong while creating a worker" +
              ", please check if your configuration is correct and your server is alive"
      end
    end
    
    def remove_worker(key)
      @middle_man.remove_job(key)
    end

    private
      # retrieves the constant of the worker name
      # based on a symbol that is passed on. The
      # following code passes back FileRetriever
      # constant so you can initialize it.
      # 
      #   klass = get_worker_class(:file_retriever)
      #   @worker = klass.new
      # 
      # Arguments:
      #     <tt>klass:</tt> Class name passed as a symbol
      # 
      # returns constant converted from a symbol
      def get_worker_class(klass)
        # convert the symbol to a string and split it
        # to an Array and join them together by
        # capitalizing the parts of the Array.
        return Object.const_get(klass.to_s.split('_').inject('') {|klass_name, slice| klass_name  << slice.capitalize})
      end
  end
end